<?php
/**
 * 支付下单service层
 * */

namespace App\Http\Services;

use App\Http\Model\FinanceBank;
use App\Http\Model\FinanceBank as FinanceBankModel;
use App\Http\Model\UnionUser;
use App\Http\Model\UserVerify as UserVerifyModel;
use App\Http\Model\FinanceKk;
use App\Http\Model\FinanceUserWallet;
use App\Http\Model\FinanceWithdrawOrder;
use App\Http\Model\Hint;
use App\Lib\CloudAccountRsa;
use http\Env\Request;
use Illuminate\Support\Facades\DB;
use Yansongda\Pay\Exceptions\GatewayException;
use Yansongda\Pay\Pay;
use App\Lib\CloudAccount;
use App\Http\Model\FinanceNotifyLog as FinanceNotifyLogModel;
use App\Http\Model\FinanceUnion;
use App\Http\Model\UnionParam;
use Exception;
use App\Lib\Bls;
use App\Http\Model\SystemConfig;

class FinanceWithdrawServices extends CommonServices
{

    private $model_finance_withdraw_order;
    private $model_finance_user_wallet;
    private $model_finance_kk;
    private $config;
    protected $financeBankModel;
    protected $userVerifyModel;
    protected $financeNotifyLogModel;
    protected $model_union_user;
    protected $model_finance_union;
    protected $model_union_param;
    protected $blsLib;
    private $systemConfigModel;
    protected $operateType = ['write','read','read_all'];// 提现限制 操作类型 写/读/读所有

    public function __construct(FinanceWithdrawOrder $financeWithdrawOrder, FinanceUserWallet $financeUserWallet, FinanceKk $financeKk,FinanceBankModel $financeBankModel, UserVerifyModel $userVerifyModel,FinanceNotifyLogModel $financeNotifyLogModel)
    {
        parent::__construct();

        $this->model_finance_withdraw_order = $financeWithdrawOrder;
        $this->model_finance_user_wallet = $financeUserWallet;
        $this->model_finance_kk = $financeKk;
        $this->config = config('pay');
        $this->financeBankModel = $financeBankModel;
        $this->userVerifyModel = $userVerifyModel;
        $this->financeNotifyLogModel = $financeNotifyLogModel;
        $this->model_union_user = new UnionUser();
        $this->model_finance_union = new FinanceUnion();
        $this->model_union_param = new UnionParam();
        $this->blsLib = new Bls();
        $this->systemConfigModel = new SystemConfig();
    }

    /**
     * 驳回提现
     * @param $order_sn
     * @return int
     */
    public function dismiss_order($order_sn){

        $order = $this->model_finance_withdraw_order->get_order($order_sn);
        if (empty($order)){
            return Hint::ERROR;
        }
        if (!redis_lock("withdraw". $order['user_id'])){
            return Hint::ERROR;
        }
        // 再次获取防止上次获取值变更
        $order = $this->model_finance_withdraw_order->get_order($order_sn);
        if($order['status'] != 0){
            return Hint::FINANCE_ORDER_COMPLETE;
        }
        $config = config('pay');
        $kk_desc = $config['wallet_change_desc']['kk_user_withdraw_dismiss'];

        DB::beginTransaction();
        try {
            $this->model_finance_withdraw_order->dismiss_order($order_sn);
            $kk_amount = intval($order['kk_amount']);
            $this->model_finance_kk->inc($order['user_id'], 0, 0, 4, $kk_amount, $kk_desc);

            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();

            write_log('error_finance', 'dismiss_order', ['msg'=>$e->getMessage(), 'line'=>$e->getLine()]);
        }

        redis_unlock("withdraw". $order['user_id']);
        return Hint::SUCCESS;

    }

    /**
     * 下单成功 回调方法
     * */
    public function cloudCountNotify($params, $type = 1){
        $code = 0;
        $msg = '操作成功';
        $data =[
            'requestParams' => $params,
        ];

        do{
            try{

                $cloudAccountInstance = CloudAccount::getInstance($type);
                $cloudAccountInstance->requestData['data'] = $params['data'] ?? '';
                $result = $cloudAccountInstance->decryptNotifyData();
                $notifyId = $result['notify_id'] ?? '';// 回调ID
                $notifyTime = $result['notify_time'] ?? '';// 回调时间
                $notifyData = $result['data'] ?? []; // 回调总数据
                $orderId = $result['data']['order_id'] ?? '';// 订单ID

                // 解析数据
                $data['resolve_data'] = $result;

                if(!$result or empty($notifyId) or empty($notifyTime) or empty($notifyData) or empty($orderId)){
                    $code = 2001;
                    $msg = '回调数据解析失败';
                    break;
                }

                $status = $notifyData['status'] ?? '';// 订单状态码
                $statusDetail =$notifyData['status_detail'] ?? '';// 订单详细状态码
                $userId = $notifyData['anchor_id'] ?? 0;// 用户ID
                $tradeSn = $notifyData['ref'] ?? '';// 外部流水号
                // todo 金额单位为分
                // $payAmount = isset($notifyData['pay']) ? ($notifyData['pay']*100) : 0;// 支付金额

                $payAmount = $notifyData['pay'] ?? 0;
                $payAmount = round($payAmount * 100,2);

                // 查询订单
                $orderData = $this->model_finance_withdraw_order->get_order($orderId);

                write_log('applyWithdraw-cloudAccount','价格对比1',var_dump($orderData['tax_after']) .' - '. var_dump($payAmount));
                write_log('applyWithdraw-cloudAccount','价格对比2',$orderData['tax_after'] .' - '. $payAmount);

                // todo 增加到返回data中记录日志
                $data['orderData'] = $orderData;

                if(empty($orderData)){
                    $code = 2002;
                    $msg = '订单不存在';
                    break;
                }
                // 校验金额
                if($orderData['tax_after'] != $payAmount){
                    $code = 2003;
                    $msg = '与申请支付额不一致';
                    break;
                }

                DB::beginTransaction();

                /**
                 * 回调支付log 查询 / 创建 / 更新
                 * */
                $checkNotifyLog = $this->financeNotifyLogModel->get(['user_id' => $userId,'order_id'=>$orderId,'trade_sn'=>$tradeSn,'status'=>$status], true);

                // todo 增加到返回data中记录日志
                $data['checkNotifyLog'] = $checkNotifyLog;

                if (empty($checkNotifyLog)) {
                    $notifyLogIdDesc = '创建失败';

                    // 创建回调支付log
                    $notifyLogId = $this->financeNotifyLogModel->create([
                        'user_id' => $userId,
                        'order_id' => $orderId,
                        'trade_sn' => $tradeSn,
                        'pay_amount' => $payAmount,// 记录日志表
                        'status' => $status,
                        'result' => json_encode($result,JSON_UNESCAPED_UNICODE),
                        'channel' => 'CLOUD_ACCOUNT',
                    ]);
                }else{
                    $notifyLogIdDesc = '更新失败';

                    // 更新
                    $notifyLogId = $this->financeNotifyLogModel->edit([
                        'log_id'=>$checkNotifyLog['log_id'],
                        'result' => json_encode($result,JSON_UNESCAPED_UNICODE),
                    ],true);
                }
                if ($notifyLogId <= 0){
                    $code = 2004;
                    $msg = '回调日志'.$notifyLogIdDesc;

                    DB::rollBack();
                    break;
                }else{
                    DB::commit();
                }

                /**
                 * 订单数据操作
                 * */
                $updateOrder = 0;
                $updateOrderDesc = '';

                // 支付成功
                // 更新订单状态
                if($status == 1 and $statusDetail == 0){
                    $updateOrder = $this->model_finance_withdraw_order->pay_order($orderId,$tradeSn,$payAmount,3,3,1);

                    $updateOrderDesc = '支付成功';
                }
                // 支付失败
                // 更新订单状态
                // todo 2:打款失败 9:打款失败(已退款，退汇或者冲正) 15:取消支付
                elseif($status == 2 or $status == 9 or $status == 15){
                    // todo 订单更新状态码为2:驳回提现，增加用户金币
                    // $this->dismiss_order($orderId);

                    // TODO 暂不操作 默认状态为4：交易失败
                    $updateOrder = $this->model_finance_withdraw_order->pay_order($orderId,$tradeSn,$payAmount,3,3,4);

                    $updateOrderDesc = '支付失败';
                }

                if ($updateOrder <= 0){
                    $code = 2005;
                    $msg = $updateOrderDesc.'，订单更新失败或不存在（或状态已更新未找到状态数据）';

                    DB::rollBack();
                }else{
                    DB::commit();
                }

                break;

            } catch (Exception $e) {
                $code = 2000;
                $msg = '服务异常';
                $data['error_msg'] = $e->getMessage();
                break;
            }
        }while(false);

        return compact('code','msg','data');
    }






    // ########## START 提现规则限制 全局设定 ########################################
    /**
     * 提现现金次数
     *
     * @param number 数量
     * @param operate_type 操作类型 write/read
     * */
    public function withdrawCashNumber($params=[]){
        $code = Hint::SUCCESS;
        $data = [];

        do {
            try {
                // 操作类型
                $operateType = $params['operate_type'] ?? '';
                if(!in_array($operateType,$this->operateType)){
                    $code = Hint::PARAM_ERROR;
                    $data['error_msg'] = '操作类型错误';
                    break;
                }

                // 提现现金次数
                $number = $params['number'] ?? 0;

                // 写条件判断
                if($operateType === 'write') {
                    if ($number < 1) {
                        $code = Hint::PARAM_ERROR;
                        $data['error_msg'] = '提现现金次数不能小于1次';
                        break;
                    }
                }

                $data['result'] = $this->model_finance_withdraw_order->withdrawCashNumber($number,$operateType);

            } catch (Exception $e) {
                // $code = Hint::ERR_SYS_FAIL;
                // $data['error_msg'] = Hint::getErrCodeMsg($code) . ':' . $e->getMessage();

                $code = Hint::ERROR;
                $data['error_msg'] = $e->getMessage();
                break;
            }
        } while (false);

        return compact('code', 'data');
    }

    /**
     * 提现银行卡张数
     *
     * @param number 数量
     * @param operate_type 操作类型 write/read
     * */
    public function withdrawBankNumber($params=[]){
        $code = Hint::SUCCESS;
        $data = [];

        do {
            try {
                // 操作类型
                $operateType = $params['operate_type'] ?? '';
                if(!in_array($operateType,$this->operateType)){
                    $code = Hint::PARAM_ERROR;
                    $data['error_msg'] = '操作类型错误';
                    break;
                }

                // 提现现金次数
                $number = $params['number'] ?? 0;

                // 写条件判断
                if($operateType === 'write') {
                    if ($number < 1) {
                        $code = Hint::PARAM_ERROR;
                        $data['error_msg'] = '提现银行卡张数不能小于1次';
                        break;
                    }
                }

                $data['result'] = $this->model_finance_withdraw_order->withdrawBankNumber($number,$operateType);

            } catch (Exception $e) {
                // $code = Hint::ERR_SYS_FAIL;
                // $data['error_msg'] = Hint::getErrCodeMsg($code) . ':' . $e->getMessage();

                $code = Hint::ERROR;
                $data['error_msg'] = $e->getMessage();
                break;
            }
        } while (false);

        return compact('code', 'data');
    }

    /**
     * 提现周期
     *
     * @param $week string 参数 0,1,2,3,4,5,6
     * @param $operateType string 操作类型 write/read
     * */
    public function withdrawWeek($params=[]){
        $code = Hint::SUCCESS;
        $data = [];

        do {
            try {
                // 操作类型
                $operateType = $params['operate_type'] ?? '';
                if(!in_array($operateType,$this->operateType)){
                    $code = Hint::PARAM_ERROR;
                    $data['error_msg'] = '操作类型错误';
                    break;
                }

                // 提现周期
                $week = $params['week'] ?? [];

                // 写条件判断
                if($operateType === 'write') {
                    if (empty($week)) {
                        $code = Hint::PARAM_ERROR;
                        $data['error_msg'] = '提现银行卡张数不能小于1次';
                        break;
                    }

                    $week = explode(',',$week);
                }

                $data['result'] = $this->model_finance_withdraw_order->withdrawWeek($week,$operateType);

            } catch (Exception $e) {
                // $code = Hint::ERROR;
                // $data['error_msg'] = Hint::getErrCodeMsg($code) . ':' . $e->getMessage();

                $code = Hint::ERROR;
                $data['error_msg'] = $e->getMessage();
                break;
            }
        } while (false);

        return compact('code', 'data');
    }

    /**
     * 提现例外用户
     *
     * @param $data array write参数 ['user_id','nickname','number','operate_nickname','status'] 用户ID 用户昵称 每日提现次数 操作人 状态（0:关闭,1:开启）
     * @param $data array read参数 ['user_id']
     * @param $operateType string 操作类型 write/read/read_all
     *
     * */
    public function withdrawExceptionUser($params=[]){
        $code = Hint::SUCCESS;
        $data = [];

        do {
            try {
                // 操作类型
                $operateType = $params['operate_type'] ?? '';
                if(!in_array($operateType,$this->operateType)){
                    $code = Hint::PARAM_ERROR;
                    $data['error_msg'] = '操作类型错误';
                    break;
                }

                $inputData = $params['data'] ?? [];

                // 写条件判断
                if($operateType === 'write') {
                    if (empty($inputData)) {
                        $code = Hint::PARAM_ERROR;
                        $data['error_msg'] = '例外用户数据不能为空';
                        break;
                    }
                }

                // 判断 写/读单条user_id不能为空
                if(in_array($operateType,['write','read']) and empty($inputData['user_id'] ?? 0)){
                    $code = Hint::PARAM_ERROR;
                    $data['error_msg'] = '用户ID不能为空';
                    break;
                }

                $data['result'] = $this->model_finance_withdraw_order->withdrawExceptionUser($inputData,$operateType);

            } catch (Exception $e) {
                // $code = Hint::ERR_SYS_FAIL;
                // $data['error_msg'] = Hint::getErrCodeMsg($code) . ':' . $e->getMessage();

                $code = Hint::ERROR;
                $data['error_msg'] = $e->getMessage();
                break;
            }
        } while (false);

        return compact('code', 'data');
    }

    /**查看提现记录
     * @param $params
     * @return array
     */
    public function getWithdrawLog($params){
        $code = Hint::SUCCESS;
        $data = array();
        do {
            $userId = $_SESSION['user_id'] ?? 0;
            if (empty($userId)) {
                $code = Hint::LOGIN_OUT;
                break;
            }
            $page = $params['page'] ?? 0;
            $pageSize = $params['pageSize'] ?? 20;
            $data = $this->model_finance_withdraw_order->getWithdrawLog($userId ,$page ,$pageSize);
        }while(false);

        return compact('code','data');
    }

    /**查看提现进度
     * @param $params
     * @return array
     */
    public function getWithdrawProcess($params){
        $code = Hint::SUCCESS;
        $data = array();
        do {
            $userId = $_SESSION['user_id'] ?? 0;
            if (empty($userId)) {
                $code = Hint::LOGIN_OUT;
                break;
            }
            $order_sn = $params['order_sn'] ?? 0;

            if(empty($order_sn)){
                $code = Hint::PARAM_ERROR;
                break;
            }
            $order = $this->model_finance_withdraw_order->get_order($order_sn);
            if(empty($order)){
                $code = Hint::ERR_DATA_NOT_EXIST;
                break;
            }
            if($order['status'] != 0 && $order['status'] != 3){
                $code = Hint::FINANCE_ORDER_COMPLETE;
                break;
            }
            $bankNoData = $this->financeBankModel->getBankCloud(array('bank_id'=>$order['bank_id']));
            $order['bank_no'] = $bankNoData['bank_no'] ?? '';
            // todo 增加到返回data中记录日志
            $order['price'] = $order['price']/100;
            $data = $order;

        }while(false);

        return compact('code','data');
    }

    /**撤回提现
     * @return int
     */
    public function recallWithdraw($params){
        $code = Hint::SUCCESS;
        $data = array();
        do {
            $userId = $_SESSION['user_id'] ?? 0;
            if (empty($userId)) {
                $code = Hint::LOGIN_OUT;
                break;
            }
            $order_sn = $params['order_sn'] ?? 0;
            if(empty($order_sn)){
                $code = Hint::PARAM_ERROR;
                break;
            }
            $order = $this->model_finance_withdraw_order->get_order($order_sn);
            if (empty($order)){
                $code = Hint::ERROR;
                break;
            }
            if (!redis_lock("recallWithdraw". $order['user_id'])){
                $code = Hint::ERROR;
                break;
            }
            // 再次获取防止上次获取值变更
            $order = $this->model_finance_withdraw_order->get_order($order_sn);
            if($order['status'] != 0 && $order['status'] != 4){
                $code = Hint::FINANCE_ORDER_COMPLETE;
                break;
            }
            DB::beginTransaction();
            try {
                $this->model_finance_withdraw_order->recall_order($order_sn);
                $kk_amount = intval($order['kk_amount']);
                $this->model_finance_kk->inc($order['user_id'], 0, 0, 23, $kk_amount, "撤回提现申请-收获金币");
    
                DB::commit();
            } catch (\Exception $e) {
                DB::rollBack();
    
                write_log('error_finance', 'recallWithdraw', ['msg'=>$e->getMessage(), 'line'=>$e->getLine()]);
            }

            redis_unlock("recallWithdraw". $order['user_id']);
        }while(false);

        return compact('code','data');
    }

    public function getCloudH5Url($user_id){
        $data = '';
        $user = $this->user->get_user($user_id);
        if(empty($user)){
            return Hint::ERR_DATA_NOT_EXIST;
        }
        $user_verify = $this->userVerifyModel->getInfoByUser(['user_id'=>$user_id ,'result_code'=>1000]);
        if(empty($user_verify) || empty($user_verify['idcard_number'])){
            return Hint::ERR_DATA_NOT_EXIST;
        }
        $cloud_user = $this->financeNotifyLogModel->getCloudUser($user_verify['idcard_number']);
        if(!empty($cloud_user) && in_array($cloud_user['status'] ,array(4,6))){
            //return Hint::ERR_DATA_EXIST;
            $user['user_id'] = $cloud_user['user_id'];
        }
        $cloudAccountInstance = CloudAccountRsa::getInstance(2);

        $cloudAccountInstance->requestData = [
            'userId' => $user['user_id'],
            'returnUrl' =>  env('APP_URL').'/html/wx/h5/index.html#/login?loginPage=withdrawal',// 跳转页面地址
            'notifyUrl' =>  env('APP_URL'). '/finance/withdraw/cloudH5Notify',// 回调地址
        ];
        $result = $cloudAccountInstance->getH5Url();
        write_log('applyWithdraw-cloudAccount','getH5url' ,$result);
        $result = json_decode($result,true);
        if($result['code'] == '000'){
            $data = $result['data']['h5_url'];
        }
        return $data;
    }

    public function cloudH5Notify($params){
        $cloudAccountInstance = CloudAccountRsa::getInstance(2);
        $cloudAccountInstance->requestData['data'] = $params['data'] ?? '';
        $result = $cloudAccountInstance->decryptNotifyData();
        $status = $result['status'] ?? 0;
        $params = array(
            'user_id'=>$result['dealer_user_id'],
            'open_id'=>$result['open_id'],
            'id_card'=>$result['id_card'],
            'name' => $result['real_name'] ,
            'status'=>$status
        );
        $this->financeNotifyLogModel->insertOrUpdateCloudUser($params);
        return array('code'=>Hint::SUCCESS ,'data'=>$result);
    }

    /**
     * @param $user_id
     * @return bool|int|string
     * @desc 查询个体工商户状态
     */
    public function cloudQuery($user_id){
        $user = $this->user->get_user($user_id);
        if(empty($user)){
            return Hint::ERR_DATA_NOT_EXIST;
        }
        $user_verify = $this->userVerifyModel->getInfoByUser(['user_id'=>$user_id,'result_code'=>1000]);
        if(empty($user_verify) || empty($user_verify['idcard_number'])){
            return Hint::ERR_DATA_NOT_EXIST;
        }
        $cloud_user = $this->financeNotifyLogModel->getCloudUser($user_verify['idcard_number']);
        if(empty($cloud_user)){
            return Hint::ERR_DATA_NOT_EXIST;
        }
        $cloudAccountInstance = CloudAccountRsa::getInstance(2);

        $cloudAccountInstance->requestData = [
            'openid' => $cloud_user['open_id']
        ];
       return $cloudAccountInstance->queryStatus();

    }

    /**处理大小额账户逻辑
     * @param $user_id
     * @return int
     */
    public function distributeProcess($user_id){
        $user_verify = $this->userVerifyModel->getInfoByUser(array('user_id'=>$user_id ,'result_code'=>1000));
        $user_company = $this->financeBankModel->getUserCompany($user_verify['idcard_number']);
        $user_type = empty($user_company) ? 0 : $user_company['type'];
        if($user_type > 0){
            return 0;
        }

        //本地数据库查询云账户状态
        $cloudUser = $this->financeNotifyLogModel->getCloudUser($user_verify['idcard_number']);


        $user_verify_users = $this->userVerifyModel->getAllIcCard($user_verify['idcard_number']);
        $user_ids = array_column($user_verify_users ,'user_id');
        if(empty($cloudUser)){
            //未注册个体工商户 提现金额不能大于3万
            $withdraw_price = $this->model_finance_withdraw_order->getMonthPriceByUserIds($user_ids);
            if($withdraw_price > $this->financeBankModel->limit_price){
                return -1;
            }
            return 1;
        }else{

            if ($cloudUser['status'] != 6) {
                $result = $this->cloudQuery($user_id);
                write_log('applyWithdraw-cloudAccount','cloudQuery' ,$result);
                $result = json_decode($result,true);
                if($result['code'] == '0000'){
                    $cloudUser = $result['data'];
                    if ($cloudUser['status'] == 6) {
                        //更新本地数据库
                        $this->financeNotifyLogModel->updateCloudUserStatus($cloudUser['status'], $user_id);
                    }
                }
            }
            $cloudUser['applyed_at'] = $cloudUser['create_time'];

            //注册成功，审核未完成
            if($cloudUser['status'] !=6){
                return -2;
            }
            //判断注册时间是否是当月（非当月直接用大额账户打款）
            if(date('Ym')-date('Ym' ,strtotime($cloudUser['applyed_at'])) >=1){
                return 2;
            }
            //是当月且注册之前有过提现用小额账户（否则用大额）
            $withdraw_price = $this->model_finance_withdraw_order->getMonthPriceByUserIds($user_ids ,0 ,strtotime($cloudUser['applyed_at']));
            if($withdraw_price > 0){
                return -3;
            }
            return 2;
        }

    }

    /**更新订单状态（挂靠和对公）
     * @param $params
     * @return int
     */
    public function updateOrderStatus($params){
        $orderData = $this->model_finance_withdraw_order->get_order($params['order_sn']);
        if(empty($orderData)){
            return Hint::ERR_DATA_NOT_EXIST;
        }
        if($orderData['status'] != 0){
            return Hint::NOT_ALLOWED;
        }
        if($orderData['user_type'] == 0){
            return Hint::AUTH_ERROR;
        }
        DB::beginTransaction();
        $r = $this->financeNotifyLogModel->create([
            'user_id' => $orderData['user_id'],
            'order_id' => $orderData['order_sn'],
            'pay_amount' => $orderData['tax_after'],// 记录日志表
            'status' => $params['status'],
            'voucher' => $params['voucher'] ?? '',
            'result' => json_encode(array('operate_id'=>$params['operate_id'] ,'msg'=>'后台手动更新','status'=>$params['status']),JSON_UNESCAPED_UNICODE),
            'channel' => 'CLOUD_ACCOUNT',
        ]);
        if(!$r){
            DB::rollBack();
        }
        $updateOrder = $this->model_finance_withdraw_order->pay_order($orderData['order_sn'],'',$orderData['tax_after'],3,0,$params['status']);
        if($updateOrder){
            DB::commit();
            return Hint::SUCCESS;
        }
        DB::rollBack();
        return Hint::ERR_FAIL;
    }

    /**
     * @param $params
     * @return int
     * @desc 获取当前用户是否可以提现打款
     */
    public function isAllowWithDraw($params)
    {
        if (!isset($params['user_id']) || empty($params['user_id'])) {
            return Hint::PARAM_ERROR;
        }
        $status = $this->model_finance_withdraw_order->isAllowWithDraw($params['user_id']);
        if (!$status) {
            return Hint::FINANCE_RECHARGE_INDIVIDUAL_LIMIT;
        }
        return Hint::SUCCESS;
    }

    public function updatePayType($params){
        $orderData = $this->model_finance_withdraw_order->get_order($params['order_sn']);
        if(empty($orderData)){
            return Hint::ERR_DATA_NOT_EXIST;
        }
        DB::beginTransaction();
        if($orderData['pay_type'] != $orderData['pay_type']){
            $r = $this->financeNotifyLogModel->create([
                'user_id' => $orderData['user_id'],
                'order_id' => $orderData['order_sn'],
                'pay_amount' => $orderData['tax_after'],// 记录日志表
                'status' => $params['status'],
                'voucher' => $params['voucher'] ?? '',
                'result' => json_encode(array('operate_id'=>$params['operate_id'] ,'msg'=>'修改实际打款的渠道','status'=>$params['status']),JSON_UNESCAPED_UNICODE),
                'channel' => 'CLOUD_ACCOUNT',
            ]);
            if(!$r){
                DB::rollBack();
            }
        }
        $this->model_finance_withdraw_order->changePayType($params['order_sn'], $params['pay_type']);

        DB::commit();
        return Hint::SUCCESS;
    }
    // ########## END   ###########################################################


    /**
     * 贝灵斯签名获取
     * */
    public function getBlsSign($str)
    {
        $sign = $this->blsLib->rsaSign($str);

        return $sign;
    }

    /**
     * 贝灵斯验签
     * */
    public function checkBlsSign($sign, $str)
    {
        $check = $this->blsLib->checkSign($sign, $str);

        return $check;
    }

    /**查看提现记录
     * @param $params
     * @return array
     */
    public function getWithdrawLogV2($userId, $page=0, $pageSize=20){
        $code = Hint::SUCCESS;
        $data = array();
        do {
            if (empty($userId)) {
                $code = Hint::LOGIN_OUT;
                break;
            }
            $data = $this->model_finance_withdraw_order->getWithdrawLog($userId ,$page ,$pageSize);
        }while(false);

        return compact('code','data');
    }

    /**
     * 是否可以提现
     * */
    public function checkWithdraw($userId){

        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];

        do {
            if (empty($userId)) {
                $code = Hint::LOGIN_OUT;
                break;
            }
            $data['userId'] = $userId;

            //主播身份
            $unionUser = $this->model_union_user->getUnionByUser([$userId]);
            if(empty($unionUser)) {
                $code = Hint::USER_NOT_CERTIFICATION;
                $msg = '非公会主播不可提现';
                break;
            }

            //对公结算公会会长不可提现
            $unionInfo = $this->model_union_user->getUnionInfoByUserId($userId);
            if(!empty($unionInfo)) {
                if($unionInfo['settle_type'] == 2) {
                    $code = Hint::USER_NOT_CERTIFICATION;
                    $msg = '对公结算公会会长不可提现';
                    break;
                }
            }

        }while(false);

        return compact('code','msg','data');
    }

    /**
     * 申请提现 app
     * */
    public function applyWithdrawV2($userId, $bankId, $price, $payType){


        $code = Hint::SUCCESS;
        $data = [
            'requestParams' => [],
        ];

        do {
            if (empty($userId) || empty($bankId) || $price<1) {
                $code = Hint::LOGIN_OUT;
                break;
            }
            $data['userId'] = $userId;
            
            //拦截黑名单 add by zxiaofee
            if((new UserFilterServices)->inExchangeAndWithdrawUserBlacklist($userId)){
                $code = Hint::FINANCE_EXCHANGE_AND_WITHDRAW_BLACKLIST;
                break;
            }

            //实名认证
            $user_verify = $this->userVerifyModel->getInfoByUser(array('user_id'=>$userId ,'result_code'=>1000));
            if(empty($user_verify)) {
                $code = Hint::USER_NOT_CERTIFICATION;
                break;
            }

            //主播身份
            $unionUser = $this->model_union_user->getUnionByUser([$userId]);
            if(empty($unionUser)) {
                $code = Hint::USER_NOT_CERTIFICATION;
                $data['error_msg'] = '非公会主播不可提现';
                break;
            }

            //对公结算公会会长不可提现
            $unionInfo = $this->model_union_user->getUnionInfoByUserId($userId);
            if(!empty($unionInfo)) {
                if($unionInfo['settle_type'] == 2) {
                    $code = Hint::USER_NOT_CERTIFICATION;
                    $msg = '对公结算公会会长不可提现';
                    break;
                }
            }

            // ################ start 例外用户限制 ################
            // 获取提现次数 int
            $withdrawCashNumber = $this->model_finance_withdraw_order->withdrawCashNumber();
            // 查询例外用户是否存在
            $withdrawExceptionUser = $this->model_finance_withdraw_order->withdrawExceptionUser(['user_id'=>$userId]);
            if(!empty($withdrawExceptionUser)){
                if($withdrawExceptionUser['status'] == 1){
                    // 覆盖提现次数
                    if ($withdrawExceptionUser['number'] > 0) {
                        $withdrawCashNumber = intval($withdrawExceptionUser['number']);
                    }
                }
            }

            // 每日可提现次数
            $getDayCount = $this->model_finance_withdraw_order->getDayCount($userId);
            if ($getDayCount >= $withdrawCashNumber){
                $code = Hint::FINANCE_WITHDRAW_COUNT_CLOSE;
                $data['error_msg'] = '今日已提现次数:'.$getDayCount.',本日提现次数已达上限:'.$withdrawCashNumber;
                break;
            }
            // ################ end 例外用户限制 ########################

            // 金币 分单位 1:100
            $kkAmount = $price * 100;

            //扣除手续费
//            $config = config('pay');
//            $kk_to_withdraw = $config['wallet_change_ratio']['kk_to_withdraw'];
            $config=$this->systemConfigModel->getDefaultSystemConfig();
            $kk_to_withdraw = $config['kk_to_withdraw']['value'];
            $tax_after = (int) ($price * $kk_to_withdraw);

            // 校验用户金币剩余
            $userData = $this->user->get_user($userId);
            if(!empty($userData)){
                $wallet = $this->model_finance_user_wallet->get_wallet($userData['user_id']);
                if(!empty($wallet)){
                    $userData['diamond_balance'] = $wallet['diamond_balance'];
                    $userData['charm_balance'] = $wallet['charm_balance'];
                    $userData['wealth_balance'] = $wallet['wealth_balance'];
                    $userData['kk_balance'] = $wallet['kk_balance'];
                }
            }

            if(empty($userData['kk_balance'] ?? 0)){
                $code = Hint::KK_NOT_ENOUGH;
                $data['error_msg'] = '金币余额为0';
                break;
            }
            if($userData['kk_balance'] < $kkAmount){
                $code = Hint::KK_NOT_ENOUGH;
                $data['error_msg'] = '提现金币账户不足';
                break;
            }

            //银行卡-贝灵斯
            if($payType == 7) {
                $bankInfo = $this->financeBankModel->getBankInfo(['id'=>$bankId,'user_id'=>$userId]);
                if(empty($bankInfo)) {
                    $code = Hint::BANK_NO_EXIST;
                    break;
                }
            }
            //支付宝-慧用工
            if($payType == 8) {
                $bankInfo = $this->model_finance_withdraw_order->getUserAlipay($userId, $bankId);
                if(empty($bankInfo)) {
                    $code = Hint::ALIPAY_NO_EXIST;
                    break;
                }
            }

            //支付宝-提现
            if($payType == 9) {
                $bankInfo = $this->model_finance_withdraw_order->getUserAlipay($userId, $bankId);
                if(empty($bankInfo)) {
                    $code = Hint::ALIPAY_NO_EXIST;
                    break;
                }
            }
           
            $remark = "打款账号:".$bankInfo['worker_account'].PHP_EOL.
                      "姓名:".$bankInfo['worker_name'].PHP_EOL.
                      "银行卡号:".$bankInfo['bank_code'].PHP_EOL.
                      "银行卡开户行:".$bankInfo['bank_source'];
            // 组织参数
            $inputParams = [];
            $inputParams['user_id'] = $userId;
            $inputParams['bank_id'] = $bankId;
            $inputParams['user_id'] = $userId;
            $inputParams['order_sn'] = create_recharge_order_sn();
            $inputParams['kk_amount'] = $kkAmount;
            $inputParams['create_timestamp'] = time();
            $inputParams['bank_id'] = $inputParams['bank_id'];
            $inputParams['price'] = $tax_after*100;
            $inputParams['pay_type'] = $payType;
            $inputParams['user_type'] = 0;
            $inputParams['account_type'] = 0;
            $inputParams['tax_after'] = $tax_after;
            $inputParams['remark'] = $remark;

            DB::beginTransaction();
            try {
                // 创建提现数据
                $data['order_id'] = $this->model_finance_withdraw_order->applyWithdraw($inputParams);
                if ($data['order_id'] <= 0) {
                    DB::rollBack();
                    $code = Hint::BANK_CREATE_FAIL;
                    break;
                }

                // 扣除金币
                $kkValue = -$inputParams['kk_amount'];
                $this->model_finance_kk->inc($userId,0,0,3,$kkValue,'用户提现-支出金币');

            } catch (Exception $e) {
                DB::rollBack();
                $code = Hint::NOT_ALLOWED;
                $data['error_msg'] = $e->getMessage();
                break;
            }
            DB::commit();

        }while(false);

        return compact('code','data');
    }

    /**
     * 后台审核同意贝灵斯提现操作
     * */
    public function payBlsOrder($orderSn)
    {
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];

        do{
            try{
                if (empty($orderSn)) {
                    $code = Hint::PARAM_ERROR;
                    break;
                }
                if (!redis_lock('LOCK:PAYBLSORDER:' . $orderSn, 10)) {
                    $code = Hint::SAME_TIME_NOT_REPEAT;
                    break;
                }

                // 查询订单
                $orderData = $this->model_finance_withdraw_order->get_order($orderSn);
                if(empty($orderData)){
                    $code = Hint::PARAM_ERROR;
                    $msg = '订单不存在';
                    break;
                }

                // 校验订单是否处理过
                if($orderData['status'] != 0){
                    $code = Hint::PARAM_ERROR;
                    $msg = '订单已处理';
                    break;
                }

                if($orderData['bank_id'] < 0){
                    $code = Hint::BANK_NO_EXIST;
                    break;
                }

                $user_verify = $this->userVerifyModel->getInfoByUser(array('user_id'=>$orderData['user_id'] ,'result_code'=>1000));
                if(empty($user_verify) || empty($user_verify['idcard_number'])){
                    $code = Hint::USER_NOT_CERTIFICATION;
                    break;
                }
                // 查询银行卡
                $bankInfo = $this->financeBankModel->getBankInfo(['id'=>$orderData['bank_id'],'user_id'=>$orderData['user_id']]);
                if(empty($bankInfo)) {
                    $code = Hint::BANK_NO_EXIST;
                    break;
                }

                // 扣除费率后金额
                $taxAfter = $orderData['tax_after'];

                //测试环境提现都是0.01
                // if (checkAppEnv()) {
                //     $taxAfter = 1;
                // }

                //发佣发起
                $body['uuid'] = $orderData['user_id'];
                $body['list'] = [
                    [
                        'workerName' => $bankInfo['user_name'],
                        'workerPhone' => $bankInfo['mobile_phone'],
                        'workerCardNo' => $bankInfo['idcard_no'],
                        'workerBankNo' => $bankInfo['bank_no'],
                        'amount' => round($taxAfter/100,2),//支付扣税后金额 接口金额单位元 保留两位小数
                        'remark' => time()."-".$orderData['order_id'],
                        'custOrderNo' => $orderSn,
                    ]
                ];
                $blsRes = $this->blsLib->payCreate($body);
                if(empty($blsRes)) {
                    $code = Hint::ERR_SYS_FAIL;
                    $msg = '提现 请求失败';
                    break;
                }
                if($blsRes['code']!=10) {
                    $code = Hint::ERR_SYS_FAIL;
                    $msg = '提现 异常:'.$blsRes['msg'];
                    break;
                }
                if(empty($blsRes['batchNo'])) {
                    $code = Hint::ERR_SYS_FAIL;
                    $msg = '提现 异常:发拥批次号获取失败';
                    break;
                }

                //更新订单状态为3：进行中
                $updateOrder = $this->model_finance_withdraw_order->pay_order(
                    $orderData['order_sn'],
                    $blsRes['batchNo'],
                    $orderData['tax_after'],
                    7,
                    0,
                    3
                );

            } catch (Exception $e) {
                $code = Hint::ERR_SYS_FAIL;
                $msg = '服务异常:'.$e->getMessage();
                break;
            }
        }while(false);

        return compact('code','msg','data');
    }

    /**
     * 提现回调 贝灵斯
     * */
    public function blsNotify($param){
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];

        do{
            if(empty($param['state']) || empty($param['batchNo']) || empty($param['custOrderNo']) || empty($param['orderNo'])) {
                break;
            }
            //6失败 7成功
            if($param['state'] != 6 && $param['state'] != 7) {
                break;
            }

            //锁
            if (!redis_lock("withdrawbls:". $param['custOrderNo'])){
                break;
            }

            $order_sn = $param['custOrderNo'];
            $out_trade_sn = $param['batchNo'];
            $out_order_id = $param['orderNo'];
            $state = $param['state'];

            // 查询订单
            $orderData = $this->model_finance_withdraw_order->get_order($order_sn);
            if(empty($orderData)){
                $code = Hint::PARAM_ERROR;
                $msg = '订单不存在';
                break;
            }
            // 校验订单是否处理过
            if($orderData['status'] != 3){
                $code = Hint::PARAM_ERROR;
                $msg = '订单已处理';
                break;
            }
            // 是否是贝灵斯
            if($orderData['pay_type'] != 7){
                $code = Hint::PARAM_ERROR;
                $msg = '不是贝灵斯提现';
                break;
            }

            //日志
            DB::beginTransaction();

            try{
                // 创建回调支付log
                $notifyLogId = $this->financeNotifyLogModel->create([
                    'user_id' => $orderData['user_id'],
                    'order_id' => $orderData['order_id'],
                    'trade_sn' => $out_trade_sn,
                    'voucher' => $out_order_id,
                    'pay_amount' => $orderData['tax_after'],
                    'status' => $state,
                    'result' => json_encode($param,JSON_UNESCAPED_UNICODE),
                    'channel' => 'BLS',
                ]);
                //6失败
                if($param['state'] == 6) {
                    $updateOrder = $this->model_finance_withdraw_order->payOrderStatus($orderData['order_id'], 3, 4, $out_order_id);
                    //退钱
                    $this->model_finance_kk->inc($orderData['user_id'], 0, 0, 4, (int)$orderData['kk_amount'], "提现失败-收获金币");
                }
                //7成功
                if($param['state'] == 7) {
                    $updateOrder = $this->model_finance_withdraw_order->payOrderStatus($orderData['order_id'], 3, 1, $out_order_id);
                }

            } catch (Exception $e) {
                DB::rollBack();
                $code = Hint::ERR_SYS_FAIL;
                $data['error_msg'] = $e->getMessage();
                break;
            }
            DB::commit();
        }while(false);

        return compact('code','msg','data');
    }

}
